/*
 * AGENT SHERPA
 *  
 * Assignement 2 of the Agent Oriented Software Engineering Course
 * M.Sc. in Advanced Software Engineering (Part-time)
 * University College Dublin www.ucd.ie
 *
 * Copyright (c) 2007 Chris Walsh, Aidan Morrisy and Iain Hull.
 * All rights reserved.
 */

package org.agentsherpa;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.agentsherpa.model.CollisionException;
import org.agentsherpa.model.Direction;
import org.agentsherpa.model.Drone;
import org.agentsherpa.model.GlobalMap;
import org.agentsherpa.model.MapLoadException;
import org.agentsherpa.model.Point;
import org.agentsherpa.model.SimulatorModel;
import org.agentsherpa.ui.MapWindow;

import com.agentfactory.platform.interfaces.Agent;
import com.agentfactory.platform.service.PlatformService;
import com.agentfactory.platform.service.PlatformServiceDescriptor;
import com.agentfactory.platform.service.PlatformServiceManager;

/**
 * SimulatorService holds the global map
 */
public class SimulatorService extends PlatformService {
    private Map<String, Drone> drones = new HashMap<String, Drone>();

    private SimulatorModel model;
    private GlobalMap map;
    private MapWindow window;

    private boolean debug = false;

    // Mandatory Platform Service Methods
    public void init(PlatformServiceDescriptor descriptor,
            PlatformServiceManager manager) {

		String file = null;
		for (int i=0; i< descriptor.numberArguments(); ++i) {
			String arg = descriptor.getArgument(i);
			System.out.println(arg);
			if (arg.equalsIgnoreCase("debug")) {
				debug = true;
			}
			else if (arg.equalsIgnoreCase("file")) {
				++i;
				file = descriptor.getArgument(i);
			}
        }

		try {
			if (file != null) {
				map = new GlobalMap(new URL(file));
                model = new SimulatorModel(map);
                window = new MapWindow(model);
                window.setVisible(true);
			}
        }
        catch (MapLoadException e) {
            e.printStackTrace();
        }
		catch (MalformedURLException e) {
			e.printStackTrace();
		}
		debugMessage("Init " + descriptor.getName() + " "
				+ descriptor.getClassName());
    }

    public void start() {
        debugMessage("Started");
    }

    public void bind(Agent agent) {
        debugMessage(agent.getName() + " has joined the service");
        model.addDrone(agent.getName());
    }

    public void unbind(Agent agent) {
        debugMessage(agent.getName() + " has left the service");
        drones.get(agent.getName()).setStatus(Drone.Status.Dead);
    }

    public void modifyBinding(String string, String string0) {
    }

    public void stop() {
        debugMessage("Terminating");
    }

    // Service Specific Methods

    /**
     * Get the Agents current location.
     */
    public synchronized Point getLocation(Agent agent) {
        Drone d = model.getDrone(agent.getName());
        
        if (d != null) {
            Point location = d.getLocation();
            debugMessage(agent.getName() + " location: " + location);
            return location;
        }
        else {
            debugMessage(agent.getName() + " location: cannot find agent");
            return Point.BadLocation;
        }
    }

    /**
     * Move the Agent in the specified direction
     * 
     * @param agent
     * @param direction
     */
    public synchronized void move(Agent agent, Direction direction) {
        Drone d = model.getDrone(agent.getName());
        
        if (drones != null) {
            try {
                model.move(d, direction);
            }
            catch (CollisionException e) {
                debugMessage("Could move drone " + d + " " + direction);
            }
        }
        else {
            debugMessage("Could not find drone " + agent.getName() + " to move");
        }
    }

    /**
     * Print a debugging message to stdout if we are in debug mode
     * 
     * @param message
     */
    private void debugMessage(String message) {
        if (debug) {
            System.out.print("[SimulatorService] ");
            System.out.println(message);
        }
    }

    public GlobalMap getMap() {
        return map;
    }
}
